import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.swing.filechooser.*;

abstract class World extends JComponent {
   private class Runner extends TimerTask {
      public void run() {
         stepAll();
         repaint();
      }
   }
   private long periodInterval=50;
   private long period=100;
   private final void setPeriod(long p) {
      period=p<=0?1:p;
      //stop(); start();
      if(isRunning()) {
         stop(); startLater(period); 
      } 
   }
   private final long getPeriod() {
      return period;
   }
   private Runner runner=null;

   public boolean canSpeedUp() {
      if(period-periodInterval<=0) return false;
      else return true;
   }

   public World(Rule r) { setRule(r); }
   public void speedUp() {
      this.setPeriod(this.getPeriod()-50);
   }
   public void slowDown() {
      this.setPeriod(this.getPeriod()+50);
   }
   public boolean isRunning() {
      return runner!=null;
   }
   public void start() {
      startLater(0);
   }
   public void startLater(long delay) {
      if(runner!=null) {
         runner.cancel();
      }
      runner=new Runner();
      Main.timer.scheduleAtFixedRate(runner, delay, period);
   }
   public void stop() {
      if(runner!=null) {
         runner.cancel();
         runner=null;
      }
      //log();
   }
   public boolean isTorus=true;
   public boolean showGrid=false;
   public boolean keepAspectRatio=true;
   public static final int EMPTY_CELL=-1;
   private Rule rule;

   public abstract void stepAll();
   public abstract void draw(Graphics g);
   public abstract void clear(); 
   public abstract void generateRandomMap(double liveRate); 
   public abstract void changeColors();

   public abstract void log();
   public abstract boolean hasPast();
   public abstract boolean hasFuture(); 
   public abstract void previous();
   public abstract void next();

   public abstract void shiftRight(); 
   public abstract void shiftLeft();  
   public abstract void shiftUp();    
   public abstract void shiftDown();  

   public final Rule getRule() { return rule; }
   public final void setRule(Rule r) {
      rule=r;
   }

   @Override public final void paintComponent(Graphics g) {
      //System.out.println("repaint");
      draw(g);
   }
   public abstract String toText();
   public abstract void fromText(String src);
   public abstract void toFile(File f) throws IOException;
   public abstract void fromFile(File f) throws IOException;
}
